function Get-NaRole {
	<#
	.SYNOPSIS
		Lists full information for all roles on the system. 
	.DESCRIPTION
		Lists full information for all roles on the system. 
	.PARAMETER Name
		List only the information associated with this role.
	.PARAMETER Server
		NaServer to query
	.EXAMPLE
		Get-NaRole
		
		return all roles on the filer
	.Example
		Get-NaRole admin
		
		return information on the admin role
	.OUTPUTS
		NetApp.SDK.NaUseradminRole[]
	.Link
		New-NaRole
		Set-NaRole
		Remove-NaRole
	#> 
	[CmdletBinding(SupportsShouldProcess=$FALSE,SupportsTransactions=$False,ConfirmImpact="None",DefaultParameterSetName="")]
	param(
	[Parameter(Position=0,ValueFromPipelineByPropertyName=$TRUE)]
	[string]
	$Name,

	[Parameter(Position=1,HelpMessage="NaServer to query")]
	[NetApp.SDK.NaServer]
	$server = (Get-NaServer)
	)
	Process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-role-list")
		if ($Name){
			$request.AddNewChild("role-name",$Name)
		}
		try {
			$result = ([xml]$server.InvokeElem($request)).results
		}
		catch [NetApp.Manage.NaApiFailedException]{
			Write-Warning $_.Exception.GetBaseException().message
			#$result = $null
			continue;
		}
		if ($?) {
			$result."useradmin-roles"."useradmin-role-info" |? {$_."name"} |% {
				return New-Object NetApp.SDK.NaUseradminRole -ArgumentList @(
				$_."name",
				$_."comment",
				[Array]($_."allowed-capabilities"."useradmin-capability-info" |%{$_.Name})
				)
			}
		}
	}
}
function New-NaRole {
	<#
	.SYNOPSIS
		Adds a role given the information provided.
	.DESCRIPTION
		Adds a role given the information provided.
	.PARAMETER Name
		Name of the role.
	.PARAMETER Capabilities
		List of capabilities the role is allowed. 
	.PARAMETER Comment
		Comment for the role. 
	.PARAMETER Server
		NaServer to query
	.EXAMPLE
		New-NaRole -Name smvi_access -Capabilities "api-*","login-http-admin","cli-ifconfig" -Comment "SMVI access"
		
		Creates a new role named 'smvi_access'
	.Example
		Get-NaRole smvi_access | New-NaRole	-server $filer2
		
		Copies the smvi_access role to filer2
	.OUTPUTS
		NetApp.SDK.NaUseradminRole[]
	.Link
		Get-NaRole
		Set-NaRole
		Remove-NaRole
	#> 
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="Low",DefaultParameterSetName="")]
	param(
	[Parameter(Mandatory=$TRUE,Position=0,ValueFromPipelineByPropertyName=$TRUE)]
	[string]
	$Name,

	[Parameter(Mandatory=$TRUE,Position=1,ValueFromPipelineByPropertyName=$TRUE)]
	[string[]]
	$Capabilities,

	[Parameter(Mandatory=$False,Position=2,ValueFromPipelineByPropertyName=$TRUE)]
	[string]
	$Comment,

	[Parameter(HelpMessage="NaServer to query")]
	[NetApp.SDK.NaServer]
	$server = (Get-NaServer)
	)
	Process {
		$AllowedCapabilities = New-Object Netapp.Manage.NaElement -ArgumentList @("allowed-capabilities")
		$Capabilities | % {
			$CapabilityInfo = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-capability-info")
			$CapabilityInfo.AddNewChild("name",$_)
			$AllowedCapabilities.AddChildElement($CapabilityInfo)
		}

		$UseradminRoleInfo = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-role-info")
		$UseradminRoleInfo.AddChildElement($AllowedCapabilities)
		$UseradminRoleInfo.AddNewChild("name",$Name)
		if ($Comment) {
			$UseradminRoleInfo.AddNewChild("comment",$Comment)
		}

		$UseradminRole = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-role")
		$UseradminRole.AddChildElement($UseradminRoleInfo)

		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-role-add")
		$request.AddChildElement($UseradminRole)

		if ($pscmdlet.ShouldProcess($Server.Server,$("Adding Role '{0}' with {1} capabilities" -f $Name, $($Capabilities -join ', ')))){
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
			if ($?){
				Get-NaRole -Name $Name -Server $Server
			}
		}
	}
}
function Set-NaRole {
	<#
	.SYNOPSIS
		Modifies a role given the information provided.  
	.DESCRIPTION
		Modifies a role given the information provided.
	.PARAMETER Name
		Name of the role.
	.PARAMETER Capabilities
		List of capabilities the role is allowed. 
	.PARAMETER Comment
		Comment for the role. 
	.PARAMETER Server
		NaServer to query
	.EXAMPLE
		Set-NaRole -Name smvi_access -Capabilities "api-*","login-http-admin"
		
		Set the capabilites on the smvi_access role.
	.Example
		Get-NaRole smvi_access | Set-NaRole -Comment "Minimum access for SMVI service account"
		
		Set the comment on the smvi_access role.
	.OUTPUTS
		NetApp.SDK.NaUseradminRole[]
	.Link
		Get-NaRole
		Set-NaRole
		Remove-NaRole
	#> 

	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="Low")]
	param(
	[Parameter(Mandatory=$TRUE,Position=0,ValueFromPipelineByPropertyName=$TRUE)]
	[string]
	$Name,

	[Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$TRUE)]
	[string[]]
	$Capabilities,

	[Parameter(Mandatory=$False,ValueFromPipelineByPropertyName=$TRUE)]
	[AllowEmptyString()]
	[string]
	$Comment,

	[Parameter(HelpMessage="NaServer to query")]
	[NetApp.SDK.NaServer]
	$server = (Get-NaServer)
	)
	Process {
		$msg = "Setting Role '{0}'" -f $Name 
		$UseradminRoleInfo = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-role-info")
		$UseradminRoleInfo.AddNewChild("name",$Name)

		if ($Capabilities) {
			$AllowedCapabilities = New-Object Netapp.Manage.NaElement -ArgumentList @("allowed-capabilities")
			$Capabilities | % {
				$CapabilityInfo = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-capability-info")
				$CapabilityInfo.AddNewChild("name",$_)
				$AllowedCapabilities.AddChildElement($CapabilityInfo)
			}
			$UseradminRoleInfo.AddChildElement($AllowedCapabilities)
			$msg = "{0} Capabilities:{1}" -f $msg, $($Capabilities -join ', ')
		}
		if ($Comment) {
			$UseradminRoleInfo.AddNewChild("comment",$Comment)
			$msg = "{0} Comment:'{1}'" -f $msg, $Comment
		}

		$UseradminRole = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-role")
		$UseradminRole.AddChildElement($UseradminRoleInfo)

		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-role-modify")
		$request.AddChildElement($UseradminRole)

		if ($pscmdlet.ShouldProcess($Server.Server,$msg)){
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
			if ($?){
				Get-NaRole -Name $Name -Server $Server
			}
		}
	}
}
function Remove-NaRole {
	<#
	.SYNOPSIS
		Deletes a role.  
	.DESCRIPTION
		Deletes a role.  
	.PARAMETER Name
		Name of a role to be deleted.
	.PARAMETER Server
		NaServer to query
	.EXAMPLE
		Remove-NaRole smvi_access
	.Link
		Get-NaRole
		Set-NaRole
		New-NaRole
	#> 
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="Low",DefaultParameterSetName="")]
	param(
	[Parameter(Mandatory=$TRUE,Position=0,ValueFromPipelineByPropertyName=$TRUE)]
	[string]
	$Name,

	[Parameter(HelpMessage="NaServer to query")]
	[NetApp.SDK.NaServer]
	$server = (Get-NaServer)
	)
	Process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-role-delete")
		$request.AddNewChild("role-name",$Name)

		if ($pscmdlet.ShouldProcess($Server.Server,"removing Role:$($Name)")){
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
		}
	}
}

function Get-NaGroup {
	<#
	.SYNOPSIS
		Lists full information for all groups on the system.
	.DESCRIPTION
		Lists full information for all groups on the system.
	.PARAMETER Name
		List only the information associated with this group
	.PARAMETER Server
		NaServer to query
	.EXAMPLE
		Get-NaGroup
		
		return all groups on the filer
	.OUTPUTS
		NetApp.SDK.NaUseradminUser[]
	.Link
		Get-NaGroup
        New-NaGroup
        Remove-NaGroup
        Rename-NaGroup
        Set-NaGroup
	#> 
	[CmdletBinding(SupportsShouldProcess=$FALSE,SupportsTransactions=$False,ConfirmImpact="None",DefaultParameterSetName="")]
	param(
	[Parameter(Position=0,ValueFromPipelineByPropertyName=$TRUE)]
	[alias("group")]
	[string]
	$Name,

	[Parameter(Position=1,HelpMessage="NaServer to query")]
	[NetApp.SDK.NaServer]
	$server = (Get-NaServer)
	)
	Process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-group-list")
		$request.AddNewChild("verbose", $True)
		if ($Name) {
			$request.AddNewChild("group-name",$Name)
		}

		Try {
			$result = ([xml]$server.InvokeElem($request)).results
		}
		catch [NetApp.Manage.NaApiFailedException]{
			Write-Warning $_.Exception.GetBaseException().message
			$result = $null
			continue;
		}
		if ($?) {
			$result."useradmin-groups"."useradmin-group-info" | % {
				return New-Object NetApp.SDK.NaUseradminGroup -ArgumentList @(
				$_."name",
				$_."comment",
				[Array]($_."allowed-capabilities"."useradmin-capability-info" |%{$_.Name}),
				[Array]($_."useradmin-roles"."useradmin-role-info" |%{$_.Name}),
				$_."rid" 
				)
			}
		}
	}
}
function New-NaGroup {
	<#
	.SYNOPSIS
		Adds a group given the information provided. 
	.DESCRIPTION
		Adds a group given the information provided. 
	.PARAMETER Name
		Name of the Group.
	.PARAMETER Role
		List of Roles the group is assigned. 
	.PARAMETER Comment
		Comment for the Group. 
	.PARAMETER Server
		NaServer to query
	.EXAMPLE
		New-NaGroup -Name smviGroup -Role smvi_access -Comment "SMVI users"
		
		Creates a new Group named 'smviGroup'
	.OUTPUTS
		NetApp.SDK.NaUseradminRole[]
	.Link
	    Get-NaGroup
        Remove-NaGroup
        Rename-NaGroup
        Set-NaGroup
	#> 
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="Low",DefaultParameterSetName="")]
	param(
		[Parameter(Mandatory=$TRUE,Position=0,ValueFromPipelineByPropertyName=$TRUE)]
		[string]
		$Name,
	
		[Parameter(Mandatory=$TRUE,Position=1,ValueFromPipelineByPropertyName=$TRUE)]
		[string[]]
		$Role,
	
		[Parameter(Mandatory=$False,Position=2,ValueFromPipelineByPropertyName=$TRUE)]
		[string]
		$Comment,
	
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer]
		$server = (Get-NaServer)
	)
	Process {
		$useradminRoles = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-roles")
		$Role | % {
			$RoleInfo = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-role-info")
			$RoleInfo.AddNewChild("name",$_)
			$useradminRoles.AddChildElement($RoleInfo)
		}

		$UseradminGroupInfo = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-group-info")
		$UseradminGroupInfo.AddChildElement($useradminRoles)
		$UseradminGroupInfo.AddNewChild("name",$Name)
		if ($Comment) {
			$UseradminGroupInfo.AddNewChild("comment",$Comment)
		}

		$UseradminGroup = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-group")
		$UseradminGroup.AddChildElement($UseradminGroupInfo)

		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-group-add")
		$request.AddChildElement($UseradminGroup)

		if ($pscmdlet.ShouldProcess($Server.Server,$("Creating Group: '{0}' with {1} roles" -f $Name, $($Role -join ', ')))){
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
			if ($?){
				Get-NaGroup -Name $Name -Server $Server
			}
		}
	}
}
function Set-NaGroup {
	<#
	.SYNOPSIS
		Modifies a group given the information provided. 
	.DESCRIPTION
		Modifies a group given the information provided. 
	.PARAMETER Name
		Name of the Group.
	.PARAMETER Role
		List of Roles the group is assigned. 
	.PARAMETER Comment
		Comment for the Group.
	.PARAMETER Server
		NaServer to query
	.EXAMPLE
		Set-NaGroup -Name grpone -Role power,audit
		
		Sets the roles for grpone to power, and audit
	.OUTPUTS
		NetApp.SDK.NaUseradminGroup[]
	.Link
	    Get-NaGroup
        New-NaGroup
        Remove-NaGroup
        Rename-NaGroup
	#> 
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="Low",DefaultParameterSetName="")]
	param(
		[Parameter(Mandatory=$TRUE,Position=0,ValueFromPipelineByPropertyName=$TRUE)]
		[string]
		$Name,
	
		[Parameter(Mandatory=$false,Position=1,ValueFromPipelineByPropertyName=$TRUE)]
		[string[]]
		$Role,
	
		[Parameter(Mandatory=$False,Position=2,ValueFromPipelineByPropertyName=$TRUE)]
		[AllowEmptyString()]
		[string]
		$Comment,
		
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer]
		$server = (Get-NaServer)
	)
	Process {
		$msg = "Setting Group '{0}'" -f $Name 
		$UseradminGroupInfo = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-group-info")
		$UseradminGroupInfo.AddNewChild("name",$Name)
		$useradminRoles = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-roles")
		if ($Role) {
			$Role | % {
				$RoleInfo = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-role-info")
				$RoleInfo.AddNewChild("name",$_)
				$useradminRoles.AddChildElement($RoleInfo)
			}
			$UseradminGroupInfo.AddChildElement($useradminRoles)
			$msg = "{0} Roles:'{1}'" -f $msg, $($Role -join ', ')
		}
		if ($Comment -or  $comment -eq "") {
			$UseradminGroupInfo.AddNewChild("comment",$Comment)
			$msg = "{0} Comment:'{1}'" -f $msg, $Comment
		}
		$UseradminGroup = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-group")
		$UseradminGroup.AddChildElement($UseradminGroupInfo)

		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-group-modify")
		$request.AddChildElement($UseradminGroup)
		
		if ($pscmdlet.ShouldProcess($Server.Server,$msg)) {
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
			if ($?){
				Get-NaGroup -Name $Name -Server $Server
			}
		}
	}
}
function Rename-NaGroup {
	<#
	.SYNOPSIS
		Rename a group 
	.DESCRIPTION
		Rename a group 
	.PARAMETER Name
		Name of the Group.
	.PARAMETER NewName
		New group name for this group. 
	.PARAMETER Server
		NaServer to query
	.EXAMPLE
		Rename-NaGroup -Name grpOne -NewName grpTwo
		
		Rename grpOne to grpTwo
	.OUTPUTS
		NetApp.SDK.NaUseradminGroup[]
	.Link
	    Get-NaGroup
        New-NaGroup
        Remove-NaGroup
        Set-NaGroup
	#> 
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="Low",DefaultParameterSetName="")]
	param(
		[Parameter(Mandatory=$TRUE,Position=0,ValueFromPipelineByPropertyName=$TRUE)]
		[string]
		$Name,
	
		[Parameter(Mandatory=$False,Position=2,ValueFromPipelineByPropertyName=$TRUE)]
		[string]
		$NewName,
	
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer]
		$server = (Get-NaServer)
	)
	Process {
		$UseradminGroupInfo = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-group-info")
		$UseradminGroupInfo.AddNewChild("name",$Name)
		$UseradminGroup = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-group")
		$UseradminGroup.AddChildElement($UseradminGroupInfo)

		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-group-modify")
		$request.AddChildElement($UseradminGroup)
		$request.AddNewChild("new-group-name",$NewName)

		if ($pscmdlet.ShouldProcess($Server.Server,"Renaming $($Name) to $($NewName)")){
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
			if ($?){
				Get-NaGroup -Name $Name -Server $Server
			}
		}
	}
}
function Remove-NaGroup {
	<#
	.SYNOPSIS
		Deletes a group.
	.DESCRIPTION
		Deletes a group.
	.PARAMETER Name
		The name of the group to be deleted.  
	.PARAMETER Server
		NaServer to query
	.EXAMPLE
		Remove-NaGroup -Name grpOne 
		
		Deletes the grpOne group
	.Link
	    Get-NaGroup
        New-NaGroup
        Rename-NaGroup
        Set-NaGroup
	#> 
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="Low",DefaultParameterSetName="")]
	param(
		[Parameter(Mandatory=$TRUE,Position=0,ValueFromPipelineByPropertyName=$TRUE)]
		[string]
		$Name,
	
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer]
		$server = (Get-NaServer)
	)
	Process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-group-delete")
		$request.AddNewChild("group-name",$Name)

		if ($pscmdlet.ShouldProcess($Server.Server,"Deleting $($Name)")){
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
		}
	}
}

function Get-NaUser {
	<#
	.SYNOPSIS
		Lists information for all administrative users on the system with the exception
		of root and snmp.
	.DESCRIPTION
		Lists information for all administrative users on the system with the exception
		of root and snmp.
	.PARAMETER User
		List only the information associated with this user.
	.PARAMETER Group
		List only the users which are a part of this group.
	.PARAMETER Server
		NaServer to query
	.EXAMPLE
		Get-NaUser
		
		return all Users on the filer
	.Example
		Get-NaUser -Group Administrators
		
		return every user who is a member of the Administrator group.
	.OUTPUTS
		NetApp.SDK.NaUseradminUser[]
	.Link
		New-NaUser
		Set-NaUser
		Remove-NaUser
	#> 
	[CmdletBinding(SupportsShouldProcess=$FALSE,SupportsTransactions=$False,ConfirmImpact="None",DefaultParameterSetName="byUser")]
	param(
	[Parameter(Position=0,ValueFromPipelineByPropertyName=$TRUE,ParameterSetName="byUser")]
	[string]
	$Name,

	[Parameter(Position=0,ValueFromPipelineByPropertyName=$TRUE,ParameterSetName="byGroup")]
	[string]
	$Group,

	[Parameter(Position=1,HelpMessage="NaServer to query",ParameterSetName="")]
	[NetApp.SDK.NaServer]
	$server = (Get-NaServer)
	)
	Process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-user-list")
		$request.AddNewChild("verbose", $True)
		if ($Name) {
			$request.AddNewChild("user-name",$Name)
		}
		elseif ($Group) {
			$request.AddNewChild("group-name",$Group)
		}
		Try {
			$result = ([xml]$server.InvokeElem($request)).results
		}
		catch [NetApp.Manage.NaApiFailedException]{
			Write-Warning $_.Exception.GetBaseException().message
			$result = $null
			continue;
		}
		if ($?) {
			$result."useradmin-users"."useradmin-user-info" | % {
				return New-Object NetApp.SDK.NaUseradminUser -ArgumentList @(
				$_."name",
				$_."full-name",
				$_."comment",
				[Array]($_."allowed-capabilities"."useradmin-capability-info" |%{$_.Name}),
				[Array]($_."useradmin-groups"."useradmin-group-info" |%{$_.Name}),
				$_."rid",
				$_."status",
				$_."password-maximum-age",
				$_."password-minimum-age"

				)
			}
		}
	}
}
function New-NaUser {
	<#
	.SYNOPSIS
		Adds a user given the information provided. 
	.DESCRIPTION
		Adds a user given the information provided.  
	.PARAMETER Name
		Name of the User.
	.PARAMETER Group
		List of groups to add the user.
	.PARAMETER Password
		Password for the user.
	.PARAMETER Comment
		Comment for the User.
	.PARAMETER FullName
		FullName of the User.
	.PARAMETER Server
		NaServer to query
	.EXAMPLE
		New-NaUser -Name smviUser -group smviAccess -password p@22W0rd -Comment "smvi user account"
		
		Creates a new user account named smviUser
	.OUTPUTS
		NetApp.SDK.NaUseradminUser[]
	.Link
		Get-NaUser
		Get-NaGroup
		Set-NaUser
		Remove-NaUser
	#> 
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="Low",DefaultParameterSetName="")]
	param(
	[Parameter(Mandatory=$TRUE,Position=0,ValueFromPipelineByPropertyName=$TRUE)]
	[string]
	$Name,

	[Parameter(Mandatory=$TRUE,Position=1,ValueFromPipelineByPropertyName=$TRUE)]
	[string[]]
	$Group,

	[Parameter(Mandatory=$TRUE,Position=2,ValueFromPipelineByPropertyName=$TRUE)]
	[string]
	$Password,

	[Parameter(Mandatory=$False,ValueFromPipelineByPropertyName=$TRUE)]
	[string]
	$Comment,

	[Parameter(Mandatory=$False,ValueFromPipelineByPropertyName=$TRUE)]
	[string]
	$FullName,

	[Parameter(HelpMessage="NaServer to query")]
	[NetApp.SDK.NaServer]
	$server = (Get-NaServer)
	)
	Process {
		$useradminGroups = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-groups")
		$group | % {
			$groupInfo = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-group-info")
			$groupInfo.AddNewChild("name",$_)
			$useradminGroups.AddChildElement($groupInfo)
		}

		$UseradminUserInfo = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-user-info")
		$UseradminUserInfo.AddChildElement($useradminGroups)
		$UseradminUserInfo.AddNewChild("name",$Name)

		if ($Comment) {
			$UseradminUserInfo.AddNewChild("comment",$Comment)
		}
		if ($FullName) {
			$UseradminUserInfo.AddNewChild("full-name",$FullName)
		}



		$UseradminUser = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-user")
		$UseradminUser.AddChildElement($UseradminUserInfo)

		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-user-add")
		$request.AddChildElement($UseradminUser)
		$request.AddNewChild("password",$Password)

		# common sense would have this encrypted... friggin netapp
		#$request.AddNewEncryptedChild("password",$Password)

		if ($pscmdlet.ShouldProcess($Server.Server,"creating user $($Name)")){
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
			if ($?){
				Get-NaUser -Name $Name -Server $Server
			}
		}
	}
}
function Set-NaUser {
	<#
	.SYNOPSIS
		Modifies a user given the information provided. 
	.DESCRIPTION
		Modifies a user given the information provided, or Changes the password of the specified user 
	.PARAMETER Name
		Name of the User.
	.PARAMETER Group
		List of groups to add the user.
	.PARAMETER Comment
		Comment for the User.
	.PARAMETER FullName
		FullName of the User.
	.PARAMETER Password
		New password for the user. Please see documentation for constraints on the password. 
	.PARAMETER OldPassword
		Current password for the user. A user with the capability 'security-passwd-change-others' 
		and at least the same capabilities as the user being changed, does not need to enter the 
		current password in order to change it to a new one. 
	.PARAMETER Server
		NaServer to query
	.EXAMPLE
		Set-NaUser -Name smviUser -comment ""
		
		remove the comment associated with smviUser
	.EXAMPLE
		Get-NaUser NBBackups | Set-NaUser -Name smviUser
		
		Copy the Groups, Comments, and Full Name from NBBackups to smviUser
	.EXAMPLE
		Set-NaUser -Name smviUser -password P@2$w0rD
		
		Change the password for smviUser
	.OUTPUTS
		NetApp.SDK.NaUseradminUser[]
	.Link
		Get-NaUser
		Get-NaGroup
		Set-NaUser
		Remove-NaUser
	#> 
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="Low",DefaultParameterSetName="modifyUser")]
	param(
	[Parameter(Mandatory=$TRUE,Position=0,ValueFromPipelineByPropertyName=$TRUE,ParameterSetName="modifyUser")]
	[Parameter(Mandatory=$TRUE,Position=0,ValueFromPipelineByPropertyName=$TRUE,ParameterSetName="Password")]
	[string]
	$Name,

	[Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$TRUE,ParameterSetName="modifyUser")]
	[alias("Groups")]
	[string[]]
	$Group,

	[Parameter(Mandatory=$False,ValueFromPipelineByPropertyName=$TRUE,ParameterSetName="modifyUser")]
	[AllowEmptyString()]
	[string]
	$Comment,

	[Parameter(Mandatory=$False,ValueFromPipelineByPropertyName=$TRUE,ParameterSetName="modifyUser")]
	[AllowEmptyString()]
	[string]
	$FullName,

	[Parameter(Mandatory=$False,ValueFromPipelineByPropertyName=$TRUE,ParameterSetName="Password")]
	[string]
	$Password,

	[Parameter(Mandatory=$False,ValueFromPipelineByPropertyName=$TRUE,ParameterSetName="Password")]
	[string]
	$OldPassword,

	[Parameter(HelpMessage="NaServer to query")]
	[NetApp.SDK.NaServer]
	$server = (Get-NaServer)
	)
	Process {
		$msg = ""
		switch ($pscmdlet.ParameterSetName)
		{
			"modifyUser"
			{
				$msg = "Setting User '{0}'" -f $Name 
				$UseradminUserInfo = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-user-info")
				$UseradminUserInfo.AddNewChild("name",$Name)

				$useradminGroups = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-groups")
				if ($Group) {
					$group | % {
						$groupInfo = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-group-info")
						$groupInfo.AddNewChild("name",$_)
						$useradminGroups.AddChildElement($groupInfo)
					}
					$msg = "{0} Groups:'{1}'" -f $msg, $($Group -join ', ')
				}
				if ($Comment -or $Comment -eq "") {
					$UseradminUserInfo.AddNewChild("comment",$Comment)
					$msg = "{0} Comment:'{1}'" -f $msg, $Comment
				}
				if ($FullName -or $fullname -eq "") {
					$UseradminUserInfo.AddNewChild("full-name",$FullName)
					$msg = "{0} FullName:'{1}'" -f $msg, $FullName
				}

				$UseradminUser = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-user")
				$UseradminUser.AddChildElement($UseradminUserInfo)
				$UseradminUserInfo.AddChildElement($useradminGroups)

				$script:request = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-user-modify")
				$request.AddChildElement($UseradminUser)
			}
			"password"
			{
				$script:request = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-user-modify-password")
				$request.AddNewChild("user-name", $Name)
				$request.AddNewChild("new-password", $Password)
				if ($OldPassword) {
					$request.AddNewChild("old-password", $OldPassword)
				}
				$msg = "Changing user '$($Name)' password"
			}
		}
		if ($pscmdlet.ShouldProcess($Server.Server,$msg)){
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
			if ($?){
				Get-NaUser -Name $Name -Server $Server
			}
		}
	}
}
function Remove-NaUser {
	<#
	.SYNOPSIS
		Deletes a user.
	.DESCRIPTION
		Deletes a user.  
	.PARAMETER Name
		Name of a user to be deleted.
	.PARAMETER Server
		NaServer to query
	.EXAMPLE
		Remove-NaUser smviUser
	.Link
		Get-NaUser
		New-NaUser
		Set-NaUser
	#> 
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="Low",DefaultParameterSetName="")]
	param(
	[Parameter(Mandatory=$TRUE,Position=0,ValueFromPipelineByPropertyName=$TRUE)]
	[string]
	$Name,

	[Parameter(HelpMessage="NaServer to query")]
	[NetApp.SDK.NaServer]
	$server = (Get-NaServer)
	)
	Process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-user-delete")
		$request.AddNewChild("user-name",$Name)

		if ($pscmdlet.ShouldProcess($Server.Server,"removing User:$($Name)")){
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
		}
	}
}

function Get-NaDomainUser {
	<#
	.SYNOPSIS
		List all of the users in a given group.
	.DESCRIPTION
		List all of the users in a given group.
	.PARAMETER Group
		List only the SIDs in this group.
	.PARAMETER Server
		NaServer to query
	.EXAMPLE
		Get-NaDomainUser -Group Administrators
		
		Return all domainusers in the administrators group
	.OUTPUTS
		PSObject[]
	.Link
		Get-NaGroup
		Add-NaDomainUser
		Remove-NaDomainUser
	#> 
	[CmdletBinding(SupportsShouldProcess=$FALSE,SupportsTransactions=$False,ConfirmImpact="None",DefaultParameterSetName="")]
	param(
		[Parameter(mandatory=$true,Position=0,ValueFromPipelineByPropertyName=$TRUE)]
		[string]
		$Group,
	
		[Parameter(Position=1,HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer]
		$server = (Get-NaServer)
	)
	begin {
		function getnaNameFromSid($sid) {
			Invoke-NaExpression "cifs lookup $($sid)" -Server $server |
				?{$_ -match "name\s=\s(?<uname>.+)$"}| Out-Null
			return [string]$Matches.uname
		}
	}
	Process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-domainuser-list")
		$request.AddNewChild("group-name",$Group)
		try {
			$result = ([xml]$server.InvokeElem($request)).results
		}
		catch [NetApp.Manage.NaApiFailedException]{
			Write-Warning $_.Exception.GetBaseException().message
			$result = $null
			continue;
		}
		if ($?) {
			$result."user-identifiers".sid| Select @{
				Name='Name'
				Expression={getnaNameFromSid $_}	
			}, @{
				Name='SID'
				Expression={$_}
			}, @{
				Name='Group'
				Expression={$Group}
			}
		}
	}
}
function Add-NaDomainUser {
	<#
	.SYNOPSIS
		Adds a nonlocal user into a group or groups. The user can be added as a SID
		or as domain\username. This API is only used in a windows environment 
	.DESCRIPTION
		Adds a nonlocal user into a group or groups. The user can be added as a SID
		or as domain\username. This API is only used in a windows environment 
	.PARAMETER USERID
		Name of the user in domain\username format. This can also be a SID (Windows
		security identifier) describing a user. A SID has the format S-1-5-21-int-int-int-rid. 
	.PARAMETER Group
		List of local groups to add the domain user to.
	.PARAMETER Server
		NaServer to query
	.EXAMPLE
		Add-NaDomainUser -UserID Get-Admin\glenn.sizemore -Group Administrators
		
		Add the domainuser Glenn.sizemore to the local administrators group.
	.Link
		Get-NaGroup
		Get-NaDomainUser
		Remove-NaDomainUser
	#> 
	[CmdletBinding(SupportsShouldProcess=$FALSE,SupportsTransactions=$False,ConfirmImpact="None",DefaultParameterSetName="")]
	param(
		[Parameter(mandatory=$true,Position=0,ValueFromPipelineByPropertyName=$TRUE)]
		[string]
		$UserID,
	
		[Parameter(mandatory=$true,Position=1,ValueFromPipelineByPropertyName=$TRUE)]
		[string[]]
		$Group,
	
		[Parameter(Position=1,HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer]
		$server = (Get-NaServer)
	)
	Process {

		$useradminGroups = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-groups")
		$group | % {
			$groupInfo = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-group-info")
			$groupInfo.AddNewChild("name",$_)
			$useradminGroups.AddChildElement($groupInfo)
		}
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-domainuser-add")
		$request.AddNewChild("user-identifier",$UserID)
		$request.AddChildElement($useradminGroups)		
		if ($pscmdlet.ShouldProcess($Server.Server,"Adding $($UserId) to $($group -join ", ")")){		
			try {
				$result = ([xml]$server.InvokeElem($request)).results
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				$result = $null
				continue;
			}
		}
	}
}
function Remove-NaDomainUser {
	<#
	.SYNOPSIS
		Removes a nonlocal user from a group or groups. The user can be removed as a
		SID or as domain\username.
	.DESCRIPTION
		Removes a nonlocal user from a group or groups. The user can be removed as a
		SID or as domain\username.
	.PARAMETER USERID
		Name of the user in domain\username format. This can also be a SID (Windows
		security identifier) describing a user. A SID has the format S-1-5-21-int-int-int-rid. 
	.PARAMETER Group
		List of local groups to remove the domain user from.
	.PARAMETER Server
		NaServer to query
	.EXAMPLE
		Add-NaDomainUser -UserID Get-Admin\glenn.sizemore -Group Administrators
		
		remove the domainuser Glenn.sizemore to the local administrators group.
	.Link
		Get-NaGroup
		Get-NaDomainUser
		Add-NaDomainUser
	#> 
	[CmdletBinding(SupportsShouldProcess=$FALSE,SupportsTransactions=$False,ConfirmImpact="None",DefaultParameterSetName="")]
	param(
		[Parameter(mandatory=$true,Position=0,ValueFromPipelineByPropertyName=$TRUE)]
		[string]
		$UserID,
	
		[Parameter(mandatory=$true,Position=1,ValueFromPipelineByPropertyName=$TRUE)]
		[string[]]
		$Group,
	
		[Parameter(Position=1,HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer]
		$server = (Get-NaServer)
	)
	Process {

		$useradminGroups = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-groups")
		$group | % {
			$groupInfo = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-group-info")
			$groupInfo.AddNewChild("name",$_)
			$useradminGroups.AddChildElement($groupInfo)
		}
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("useradmin-domainuser-delete")
		$request.AddNewChild("user-identifier",$UserID)
		$request.AddChildElement($useradminGroups)		
		if ($pscmdlet.ShouldProcess($Server.Server,"Removing $($UserId) from $($group -join ", ")")){		
			try {
				$result = ([xml]$server.InvokeElem($request)).results
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				$result = $null
				continue;
			}
		}
	}
}